﻿using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;

namespace iOSClub.CheckInApi.DataModels;

public sealed class CheckContext : DbContext
{
    public CheckContext(DbContextOptions<CheckContext> options) : base(options)
    {
        Users = Set<UserModel>();
    }

    public DbSet<UserModel> Users { get; init; }
    public DbSet<CheckModel> Checks { get; init; }
    public DbSet<SeriesModel> Series { get; init; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<UserModel>().HasMany(x => x.Checks).WithOne(x => x.User)
            .HasForeignKey(x => x.UserId);
        modelBuilder.Entity<UserModel>().HasMany(x => x.Series)
            .WithMany(x => x.Users);

        modelBuilder.Entity<SeriesModel>().HasMany(x => x.Checks)
            .WithOne(x => x.Series)
            .HasForeignKey(x => x.SeriesId)
            .IsRequired(false);
    }
}

public static class DataTool
{
    public static string StringToHash(string s)
    {
        var data = Encoding.UTF8.GetBytes(s);
        var hash = MD5.HashData(data);
        var hashStringBuilder = new StringBuilder();
        foreach (var t in hash)
            hashStringBuilder.Append(t.ToString("x2"));
        return hashStringBuilder.ToString();
    }

    public static string GetProperties<T>(T t)
    {
        var builder = new StringBuilder();
        if (t == null) return builder.ToString();

        var properties = t.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);

        if (properties.Length <= 0) return builder.ToString();

        foreach (var item in properties)
        {
            var name = item.Name;
            var value = item.GetValue(t, null);
            if (item.PropertyType.IsValueType || item.PropertyType.Name.StartsWith("String"))
            {
                builder.Append($"{name}:{value ?? "null"},");
            }
        }

        return builder.ToString();
    }
}

public abstract class DataModel
{
    public override string ToString() => $"{GetType()} : {DataTool.GetProperties(this)},Time:{DateTime.Now.Ticks}";
}

// ReSharper disable once UnusedType.Global
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<CheckContext>
{
    public CheckContext CreateDbContext(string[] args)
    {
        var optionsBuilder = new DbContextOptionsBuilder<CheckContext>();
        optionsBuilder.UseSqlite("Data Source=Data.db");
        return new CheckContext(optionsBuilder.Options);
    }
}